import re

from fastapi import FastAPI, Request
from fastapi.exceptions import HTTPException
from pydantic_validation_decorator import FieldValidationError
from sqlalchemy.exc import IntegrityError, DataError, SQLAlchemyError

from common.exceptions.exception import (
    AuthException,
    LoginException,
    ModelValidatorException,
    PermissionException,
    ServiceException,
    ServiceWarning,
)
from common.utils.log_util import logger
from common.utils.response_util import jsonable_encoder, JSONResponse, ResponseUtil


def handle_exception(app: FastAPI):
    """
    全局异常处理
    """

    # 自定义token检验异常
    @app.exception_handler(AuthException)
    async def auth_exception_handler(request: Request, exc: AuthException):
        return ResponseUtil.unauthorized(data=exc.data, msg=exc.msg)

    # 自定义登录检验异常
    @app.exception_handler(LoginException)
    async def login_exception_handler(request: Request, exc: LoginException):
        return ResponseUtil.failure( msg=exc.msg)

    # 自定义模型检验异常
    @app.exception_handler(ModelValidatorException)
    async def model_validator_exception_handler(request: Request, exc: ModelValidatorException):
        logger.warning(exc.msg)
        return ResponseUtil.failure( msg=exc.msg)

    # 自定义字段检验异常
    @app.exception_handler(FieldValidationError)
    async def field_validation_error_handler(request: Request, exc: FieldValidationError):
        logger.warning(exc.msg)
        return ResponseUtil.failure(msg=exc.msg)

    # 自定义权限检验异常
    @app.exception_handler(PermissionException)
    async def permission_exception_handler(request: Request, exc: PermissionException):
        return ResponseUtil.forbidden(data=exc.data, msg=exc.msg)

    # 自定义服务异常
    @app.exception_handler(ServiceException)
    async def service_exception_handler(request: Request, exc: ServiceException):
        logger.error(exc.msg)
        return ResponseUtil.error( msg=exc.msg)

    # 自定义服务警告
    @app.exception_handler(ServiceWarning)
    async def service_warning_handler(request: Request, exc: ServiceWarning):
        logger.warning(exc.msg)
        return ResponseUtil.failure( msg=exc.msg)

    @app.exception_handler(IntegrityError)
    async def mysql_integrity_exception_handler(request: Request, exc: IntegrityError):
        error_info = str(exc.orig)
        # 处理唯一键冲突异常
        if "Duplicate entry" in error_info:
            # 使用正则表达式提取重复的值和字段名
            match = re.search(r"Duplicate entry '([^']+)' for key '([^']+)'", error_info)
            if match:
                duplicate_value = match.group(1)
                field_name = match.group(2)
                logger.warning("MySQL 唯一键冲突异常: 字段 %s 的值 %s 已存在", field_name, duplicate_value)
                return ResponseUtil.failure(msg=f"字段 {field_name} 的值 {duplicate_value} 已存在，违反唯一键约束")
            else:
                logger.warning("MySQL 唯一键冲突异常: %s", error_info)
                return ResponseUtil.failure(msg="数据已存在，违反唯一键约束")
        # 处理非空约束异常
        elif "Column" in error_info and "cannot be null" in error_info:
            # 提取字段名
            start_index = error_info.find("Column '") + len("Column '")
            end_index = error_info.find("'", start_index)
            field_name = error_info[start_index:end_index]
            logger.warning("MySQL 非空约束异常: 字段 %s 不能为空", field_name)
            return ResponseUtil.failure(msg=f"字段 {field_name} 不能为空，请检查必填字段")
        else:
            # 如果不是唯一键冲突和非空约束，当作其他 IntegrityError 处理
            logger.error("数据库完整性错误: %s", error_info)
            return ResponseUtil.failure(msg="数据库完整性错误，请检查数据")
    # 处理其他http请求异常
    @app.exception_handler(HTTPException)
    async def http_exception_handler(request: Request, exc: HTTPException):
        msg=exc.detail
        if msg=="Not authenticated":
            msg="未授权,访问系统资源失败!"
        return JSONResponse(
            content=jsonable_encoder(msg), status_code=exc.status_code
        )

    @app.exception_handler(DataError)
    async def data_error_handler(request: Request, exc: DataError):
        error_info = str(exc)
        logger.error("数据错误: %s", error_info)

        # 尝试从错误信息中提取字段名
        field_name = None
        field_pattern = r"column '([^']+)'"
        field_match = re.search(field_pattern, error_info)
        if field_match:
            field_name = field_match.group(1)

        if field_name:
            msg = f"字段 '{field_name}' 的数据不符合要求。"
        else:
            msg = f"数据错误: {error_info}"

        return ResponseUtil.failure(msg=msg)

    # 处理其他异常
    @app.exception_handler(Exception)
    async def exception_handler(request: Request, exc: Exception):
        """
   异常处理
   """
        if exc is None:
            # 如果异常对象为空，返回一个默认的错误响应
            return ResponseUtil.failure(code=500, msg="系统错误")

        if isinstance(exc, SQLAlchemyError):
            '''数据库异常'''
            db_error_msg ='数据库请求异常'
            return ResponseUtil.failure(msg=db_error_msg)
        elif isinstance(exc, (SyntaxError, TypeError, ValueError, AttributeError, KeyError, ArithmeticError)):
            run_error_msg = f"代码执行错误,请检查代码拼接块"
            return ResponseUtil.failure(msg=run_error_msg)
        else:
            '''默认的异常'''
            # 如果异常对象没有 code 和 msg 属性，提供默认值
            code = getattr(exc, 'code', 500)
            msg = getattr(exc, 'msg',"系统出错,请检查是否启动")
            data = getattr(exc, 'data', None)
            return ResponseUtil.failure(code=code, msg=msg, data=data)
    # 处理其他未定义的异常
class AllExceptions:
    EXCEPTIONS = (
        LoginException,
        AuthException,
        ModelValidatorException,
        FieldValidationError,
        PermissionException,
        ServiceException,
        ServiceWarning,
        HTTPException,
        IntegrityError,
        DataError
    )